﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace comm.world
{
    public abstract class BAction : BObject
    {
        public const string UNDEFINED_KEY = "UNDEFINED";

        string _execKey = UNDEFINED_KEY;
        public string ExecKey { get { return _execKey; } }

        public string BeginExecKey { get { return _beginExecKey; } }

        objst.ActionStepType _execStepType = objst.ActionStepType.END;
        public objst.ActionStepType ExecStepType
        {
            get { return _execStepType; }
            private set
            {
                var old = _execStepType;
                _execStepType = value;
                if (old != value)
                {
                    OnExecStepChange();
                }
            }
        }

        public long ExecTimeOffset { get { return (long)_msCount; } }

        Dictionary<string, objst.ObjAction> _acDic = null;
        bool _beginRun = false;
        uint _beginTime = 0, _endTime = 0;
        uint _execTime = 0;
        double _msCount = 0;
        string _beginExecKey = null, _waitExecKey = null;

        public BAction(Dictionary<string, objst.ObjAction> acDic, string execAcKey, long useMS = 0)
        {
            _acDic = acDic;
            Exec(execAcKey, useMS);
        }

        objst.ObjAction GetAction(string acKey)
        {
            objst.ObjAction ac = null;
            _acDic.TryGetValue(acKey, out ac);
            return ac;
        }

        protected virtual void OnExecStepChange()
        {
        }
        protected virtual void OnExecBegin()
        {
            //Console.WriteLine(BeginExecKey + " begin");
        }
        protected virtual void OnExecEnd()
        {
            //Console.WriteLine(ExecKey + " end");
        }

        public void End()
        {
            _beginRun = false;
            ExecStepType = objst.ActionStepType.END;
            _waitExecKey = null;
            OnExecEnd();
        }
        public void Exec(string acKey, long useMS = 0)
        {
            var ac = GetAction(acKey);
            if (ac != null)
            {
                if (ExecStepType == objst.ActionStepType.EXEC || ExecStepType == objst.ActionStepType.ENDING)
                {
                    _waitExecKey = acKey;
                    if (_execTime == 0)
                    {
                        _msCount = _beginTime;
                        ExecStepType = objst.ActionStepType.ENDING;
                    }
                    return;
                }
                _beginRun = false;
                ExecStepType = objst.ActionStepType.BEGIN;
                _beginExecKey = acKey;
                _beginTime = ac.BeginTime;
                _execTime = ac.ExecTime.HasValue ? ac.ExecTime.Value : 0;
                _endTime = ac.EndTime;
                _msCount = useMS;
                _beginRun = true;
                OnExecBegin();
            }
            else
            {
                //Console.WriteLine("acKey:" + acKey + " not found!");
            }
        }

        protected override void OnUpdate(TimeStat timeStat)
        {
            if (_beginRun)
            {
                _msCount += timeStat.ElapsedTime.TotalMilliseconds;
                if (ExecStepType == objst.ActionStepType.BEGIN && _msCount >= _beginTime)
                {
                    _execKey = _beginExecKey;
                    _beginExecKey = null;
                    ExecStepType = objst.ActionStepType.EXEC;
                }
                if (ExecStepType == objst.ActionStepType.EXEC && _execTime > 0 && _msCount >= _execTime + _beginTime)
                {
                    ExecStepType = objst.ActionStepType.ENDING;
                }
                if (ExecStepType == objst.ActionStepType.ENDING && _msCount >= _execTime + _beginTime + _endTime)
                {
                    var waitExecKey = _waitExecKey;
                    End();
                    if (waitExecKey != null)
                    {
                        Exec(waitExecKey);
                    }
                }
            }
        }
    }
}
